package util;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * 使用DbUtils对外提供数据库操作方式
 * 提供
 *      update
 *      queryBean
 *      queryBeanList
 *      queryArray
 *      queryArrayList
 *      queryMap
 *      queryMapList
 */
public class BaseDao {
    private QueryRunner queryRunner = new QueryRunner(JdbcUtil.getDataSource());

    /**
     * 通用update方法，用于处理insert, delete, update方法，所需参数是执行的目标SQL语句
     * 和对应的SQL语句参数
     *
     * @param sql        String类型的SQL语句
     * @param parameters 对应的当前SQL语句的Object类型不定长参数【不定长参数类内是一个数组】
     * @return 当前SQL语句执行操作对应数据表的影响行数
     * @throws SQLException SQL语句异常
     */
    public int update(String sql, Object... parameters) throws SQLException {
        return queryRunner.update(sql, parameters);
    }

    /**
     * 用于查询指定JavaBean规范了类对象方法，查询单个数据。
     *
     * @param sql        查询使用的SQL语句
     * @param cls        用户指定当前结果集数据行对应的数据类型，要求类型符合JavaBean规范，并且参数是Class类型，提供反射操作的基本
     * @param parameters 对应当前SQL语句的参数
     * @param <T>        泛型，用于约束当前查询结果集对应的具体类型是什么
     * @return 返回查询结果集数据行用户指定的类对象
     * @throws SQLException SQL异常
     */
    public <T> T queryBean(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new BeanHandler<>(cls), parameters);
    }

    /**
     * 用于查询指定JavaBean规范类对象方法，查询多个数据，返回值结果是一个List集合，保存数据类型为用户指定类型
     *
     * @param sql        查询使用的SQL语句
     * @param cls        用户指定当前结果集数据行对应的数据类型，要求类型符合JavaBean规范，并且参数是Class类型，提供反射操作的基本
     * @param parameters 对应当前SQL语句的参数
     * @param <T>        泛型，用于约束当前查询结果集对应的具体类型是什么
     * @return 返回值是List集合，保存的元素是用户指定的元素本身
     * @throws SQLException SQL异常
     */
    public <T> List<T> queryBeanList(String sql, Class<T> cls, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new BeanListHandler<>(cls), parameters);
    }

    /**
     * 查询一行数据，数据的所有内容根据查询使用的SQL语句查询顺序，存储到一个Object类型数组中，返回
     *
     * @param sql        查询使用的SQL语句
     * @param parameters 对应当前SQL语句的参数
     * @return Object类型数组，保存查询结果集中的一行数据所有内容，顺序根据SQL语句查询字段数据明确
     * @throws SQLException SQL异常
     */
    public Object[] queryArray(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new ArrayHandler(), parameters);
    }

    /**
     * 查询多行数据，查询数据结果集中的每一行数据看作是一个Object类型数组，数组的存储内容顺序根据SQL语句查询字段要求完成。
     * 所有的Object数组存储到一个List集合中
     *
     * @param sql        查询使用的SQL语句
     * @param parameters 对应当前SQL语句的参数
     * @return List集合中存储所有数据行对应的Object类型数组
     * @throws SQLException SQL异常
     */
    public List<Object[]> queryArrayList(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new ArrayListHandler(), parameters);
    }

    /**
     * 查询一行数据行，查询数据的字段名作为Map双边队列的Key，数据作为Value，返回值类型是一个Map<String, Object>双边队列
     *
     * @param sql        查询使用的SQL语句
     * @param parameters 对应当前SQL语句的参数
     * @return Map<String, Object>双边队列
     * @throws SQLException SQL异常
     */
    public Map<String, Object> queryMap(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new MapHandler(), parameters);
    }

    /**
     * 查询多行数据，查询结果集中的所有数据行，每一行数据对应一个Map<String,Object>双边队列，结果集字段名对应Key，数据对应Value。
     * 所有数据存储到一个List集合集合中，返回数据是一个List<Map<String, Object>
     *
     * @param sql        查询使用的SQL语句
     * @param parameters 对应当前SQL语句的参数
     * @return List<Map < String, Object> 对应当场查询结果集的所有数据的List集合，每一行数据对应一个Map双边队列
     * @throws SQLException SQL异常
     */
    public List<Map<String, Object>> queryMapList(String sql, Object... parameters) throws SQLException {
        return queryRunner.query(sql, new MapListHandler(), parameters);
    }
}
